package ui.swing.tree.eventhandle;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;

import ui.swing.common.SwingUtil;



public class TreeWithCRUD extends JFrame implements ActionListener,TreeModelListener{

	private static final long serialVersionUID = -6516436057733254443L;
	
	JTree tree = null;
	JLabel label = null;
	// 原有节点名
    String nodeName = null;

	public TreeWithCRUD() {
		super("在TreeFromTreeModelDemo的基础上增加ModelListener");
		setBounds(200,200,300,400);
		
		DefaultMutableTreeNode root=new DefaultMutableTreeNode("资源管理器");	

		tree = new JTree(root);
		//设置JTree为可编辑的
		tree.setEditable(true);
		// 设置行高
		tree.setRowHeight(20);
		// 使Tree加入检测Mouse事件，以便取得节点名称（仔细看下）
		tree.addMouseListener(new MouseEventHandler());
		tree.getModel().addTreeModelListener(this);

		// 操作面板
		JPanel panel=new JPanel();
	    JButton b=new JButton("新增节点");
	    b.addActionListener(this);
	    panel.add(b);
	    b=new JButton("删除节点");
	    b.addActionListener(this);
	    panel.add(b);
	    b=new JButton("清除所有节点");
	    b.addActionListener(this);
	    panel.add(b);

		JScrollPane jsp = new JScrollPane();
		jsp.setViewportView(tree);
		
		label = new JLabel("Action");
		
		getContentPane().add(panel, BorderLayout.NORTH);
		getContentPane().add(jsp, BorderLayout.CENTER);
		getContentPane().add(label, BorderLayout.SOUTH);
		//pack();
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setVisible(true);
	}

	public void treeNodesChanged(TreeModelEvent e) {
		TreePath treePath = e.getTreePath();
		System.out.println(treePath);

		// 下面这行由TreeModelEvent取得的DefaultMutableTreeNode为节点的父节点，而不是用户点选
        // 的节点，这点读者要特别注意。要取得真正的节点需要再加写下面6行代码.
		DefaultMutableTreeNode sourceParentNode = (DefaultMutableTreeNode)treePath.getLastPathComponent();

		// getChildIndices()方法会返回目前修改节点的索引值。由于我们只修改一个节点，因此节点索引值就放在index[0]
        // 的位置，若点选的节点为root node,则getChildIndices()的返回值为null
		int[] indexes = e.getChildIndices();
		if(indexes == null)
			return;
		DefaultMutableTreeNode sourceNode = (DefaultMutableTreeNode)sourceParentNode.getChildAt(indexes[0]);
		label.setText('[' + nodeName + ']'+ "更改名字为：" + (String)sourceNode.getUserObject());
	}

	public void treeNodesInserted(TreeModelEvent e) {
		label.setText("新增了节点");
	}

	public void treeNodesRemoved(TreeModelEvent e) {
		label.setText("删除节点");
	}

	public void treeStructureChanged(TreeModelEvent e) {
		label.setText("清除了所有节点");
	}

	class MouseEventHandler extends MouseAdapter {
		@Override
		// 注意下面的两种方法取得当前的treeNode，一种是tree.getSelectionPath()；一种比较另类，通过鼠标点击的location定位TreePath
		public void mousePressed(MouseEvent e) {

			JTree tree = (JTree)e.getSource();
			
			/* JTree的getRowForLocation()方法会返回鼠标点取得地点（location）对应的节点的列索引值。
			 * 如果鼠标点取的location没有组件，则会返回-1
			 * 例如本例中，“本机磁盘(D:)”的列索引值为4,此索引值会随着其他数据夹的打开或收起而变更
			 * 但“资源管理器”的列索引值恒为0. 
			 */
			//int row4Location = tree.getRowForLocation(e.getX(), e.getY());
			//if(row4Location == -1)
			//	return;
			/* JTree的getPathForRow()方法会取得从root node到点选节点的一条path,此path为一条直线，如程序运行的图示
             * 若你点选“本机磁盘(E:)”,则Tree Path为"资源管理器"-->"我的电脑"-->"本机磁盘(E:)",因此利用TreePath
             * 的getLastPathComponent()方法就可以取得所点选的节点.
             */
			//TreePath treepath = tree.getPathForRow(row4Location);
			
			TreePath treepath=tree.getSelectionPath();
			if(treepath != null)
			{
				TreeNode treenode = (TreeNode) treepath.getLastPathComponent();
				nodeName = treenode.toString();
			}
			label.setText("你选取了:" + nodeName);
		}
	}

	public void actionPerformed(ActionEvent e) {
		if("新增节点".equals(e.getActionCommand())) {
			// 取得选取的节点
			TreePath selectedPath = tree.getSelectionPath();
			DefaultMutableTreeNode parentOfNewNode;
			if(selectedPath != null) {
				parentOfNewNode = (DefaultMutableTreeNode)selectedPath.getLastPathComponent();
			} else {
				parentOfNewNode = (DefaultMutableTreeNode)tree.getModel().getRoot();
			}
			// 建立新节点
			DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("我是新节点:)");
			newNode.setAllowsChildren(true);
			// 将新节点作为选取的节点的子节点
			/* newNode.setParent(parentOfNewNode);
			 * parentOfNewNode.add(newNode);
			 * 这个方法是不行的，只用于添加已经有了的节点（移动？）
			 **/
			((DefaultTreeModel)tree.getModel()).insertNodeInto(newNode, parentOfNewNode, parentOfNewNode.getChildCount());
			
			/* tree的scrollPathToVisible()方法在使Tree会自动展开文件夹以便显示所加入的新节点。若没加这行则加入的新节点
			 * 会被 包在文件夹中，你必须自行展开文件夹才看得到。
			 */
			tree.scrollPathToVisible(new TreePath(newNode.getPath()));  	 	 
			label.setText("新增节点成功");
		}
		if("删除节点".equals(e.getActionCommand())) {
			TreePath selectedPath = tree.getSelectionPath();
			if( selectedPath != null)
			{
				DefaultMutableTreeNode nodeToBeDeleted = (DefaultMutableTreeNode)selectedPath.getLastPathComponent();
				TreeNode parent=(TreeNode)nodeToBeDeleted.getParent();
				if(parent != null) {
					((DefaultTreeModel)tree.getModel()).removeNodeFromParent(nodeToBeDeleted);
					label.setText("删除节点成功");
				}
			}
		}
		if("清除所有节点".equals(e.getActionCommand())) {
			DefaultMutableTreeNode root =(DefaultMutableTreeNode)((DefaultTreeModel)tree.getModel()).getRoot();
			root.removeAllChildren();
			((DefaultTreeModel)tree.getModel()).reload();
			label.setText("清除所有节点成功");
		}
	}
	
	public static void main(String[] args) {
		SwingUtil.setLookAndFeel();
		new TreeWithCRUD();
	}
}